<?php
declare (strict_types = 1);

namespace app\frontend\controller;

use app\frontend\model\ProjectContent;
use app\frontend\model\UserProject;
use think\facade\Db;
use think\facade\Filesystem;
use think\facade\Validate;

class Project extends Base
{
    // 项目列表页
    public function index()
    {
        return view();
    }

    // 项目列表数据接口
    public function list()
    {
        $page = request()->param('page');
        $limit = request()->param('limit');
        $name = request()->param('name');

        $userInfo = session('userInfo');
        $userProjects = UserProject::where('user_id', $userInfo['id'])->column('project_id');

        $projectList = \app\frontend\model\Project::field('id,name,create_time')
            ->where([
                ['name', 'like', '%'.$name.'%'],
                ['id', 'in', $userProjects]
            ])
            ->paginate([
                'list_rows' => $limit,
                'var_page' => 'page',
                'page' => $page,
                'query' => [
                    'name' => $name
                ]
            ]);
        $projectListData = $projectList->toArray()['data'];

        $data = [
            'code' => 0,
            'msg' => '',
            'count' => $projectList->total(),
            'data' => $projectListData
        ];

        return json($data);
    }

    // 项目添加页
    public function add()
    {
        return view('');
    }

    // 富文本编辑器图片上传接口
    public function uploadImg()
    {
        $files = request()->file();
        $saveName = [];
        try {
            validate(['image' => ['fileSize:1024000', 'fileExt:jpg,png,gif,jpeg']])
                ->check($files);
            $ds = DIRECTORY_SEPARATOR;
            foreach($files as $file) {
                $saveName[] = $ds.'uploads'.$ds . Filesystem::disk('public')->putFile('image'.$ds.'temp', $file);
            }
        } catch (\think\exception\ValidateException $e) {
            return json([
                'errno' => 1,
                'data' => $e->getMessage()
            ]);
        }

        // 根据操作系统的不同对返回的saveName格式进行处理
        foreach ($saveName as &$v) {
            if ($ds == '/') {
                $v = str_replace('\\', $ds, $v);
            } else {
                $v = str_replace('/', $ds, $v);
            }
        }
        unset($v);

        return json([
            'errno' => 0,
            'data' => $saveName
        ]);
    }

    // 项目添加页面保存接口
    public function save()
    {
        $params['name'] = trim(input('post.name', '', 'strip_tags'));
        $params['content'] = input('post.content', '');

        $validate = Validate::rule([
            'name|名称' => 'require|max:20'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);

        // 启动事务
        Db::startTrans();
        try {
            $projectModel = \app\frontend\model\Project::create($params);
            $userInfo = session('userInfo');
            UserProject::create([
                'user_id' => $userInfo['id'],
                'project_id' => $projectModel->id
            ]);

            // 插入task_content表
            ProjectContent::create([
                'project_id' => $projectModel->id,
                'content' => htmlspecialchars($newContent)
            ]);
            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 2,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '保存成功'
        ]);
    }

    // 项目编辑页
    public function edit()
    {
        // 管理员信息
        $id = (int)input('get.id', '', 'strip_tags');
        $project = \app\frontend\model\Project::field('id,name')
            ->find($id);
        $project->projectContent;

        $projectData = [
            'id' => $id,
            'name' => $project['name'],
            'content' => $project['projectContent']['content']
        ];

        return view('', [
            'project' => $projectData
        ]);
    }

    // 项目编辑页面保存接口
    public function update()
    {
        // 管理员信息
        $params['id'] = (int)trim(input('post.id', '', 'strip_tags'));
        $params['name'] =  trim(input('post.name', '', 'strip_tags'));
        $params['content'] = input('post.content', '');

        // 格式验证
        $validate = Validate::rule([
            'id|id' => 'require|integer',
            'name|名称' => 'require|max:20'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        $projectModel = \app\frontend\model\Project::find($params['id']);

        // 富文本内容处理
        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);
        // 找到原先content中存在但是富文本编辑器在本次编辑中删除的图片的url，然后删除该图片
        // 找到数据库中存储的content
        $oldContent = ProjectContent::where('project_id', $params['id'])->find();
        $oldContent = htmlspecialchars_decode($oldContent['content']);
        // 正则表达式匹配查找图片路径
        $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
        preg_match_all($pattern, $oldContent, $oldMatches);
        $oldImgs = $oldMatches[1];
        preg_match_all($pattern, $newContent, $newMatches);
        $newImgs = $newMatches[1];
        // 删除图片
        for ($i=0; $i < count($oldImgs); $i++) {
            if (!in_array($oldImgs[$i], $newImgs)) {
                unlink('.' . $oldImgs[$i]);
            }
        }

        // 将数据存入数据库
        Db::startTrans();
        try {
            // 更新requirement表
            $projectModel->name = $params['name'];
            $projectModel->save();
            // 更新project_content表
            $projectContent = ProjectContent::where('project_id', $params['id'])->find();
            $projectContent->content =htmlspecialchars($newContent);
            $projectContent->save();

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            // 返回操作失败信息
            return json([
                'code' => 2,
                'msg' => '修改失败'
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '修改成功'
        ]);
    }

    // 项目列表删除接口
    public function delete()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        $task = \app\frontend\model\Task::where('project_id', $id)->find();
        if (!empty($task)) {
            return json([
                'code' => 1,
                'msg' => '请先删除该项目下的所有任务'
            ]);
        }

        // 启动事务
        Db::startTrans();
        try {
            \app\frontend\model\Project::destroy($id);
            UserProject::destroy(function ($query) use ($id) {
                $query->where('project_id', $id);
            });

            // 删除富文本编辑器内容及内容中的图片
            $projectContentModel = ProjectContent::where('project_id', $id)->find();
            $content = htmlspecialchars_decode($projectContentModel->content);
            $projectContentModel->delete();

            // 删除content中的图片
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $images = $matches[1];
            // 删除图片
            for ($i=0; $i < count($images); $i++) {
                unlink('.' . $images[$i]);
            }

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 2,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    // 项目列表多选删除接口
    public function deleteMulti()
    {
        $ids = input('post.ids', '', 'strip_tags');

        $task = \app\frontend\model\Task::where('project_id', 'in', $ids)->find();
        if (!empty($task)) {
            return json([
                'code' => 1,
                'msg' => '请先删除所选项目下的所有任务'
            ]);
        }

        // 挨个删除，如果失败则回滚
        foreach ($ids as $id) {
            Db::startTrans();
            try {
                \app\frontend\model\Project::destroy($id);
                UserProject::destroy(function ($query) use ($id) {
                    $query->where('project_id', '=', $id);
                });

                $projectContentModel = ProjectContent::where('project_id', $id)->find();
                $content = htmlspecialchars_decode($projectContentModel->content);
                $projectContentModel->delete();

                // 删除content中的图片
                $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
                preg_match_all($pattern, $content, $matches);
                $images = $matches[1];
                // 删除图片
                for ($i=0; $i < count($images); $i++) {
                    unlink('.' . $images[$i]);
                }

                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                // 返回操作失败信息
                return json([
                    'code' => 3,
                    'msg' => $e->getMessage()
                ]);
            }
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    /**
     * 富文本编辑器文本内容处理
     * @param string $content 富文本编辑器文本内容
     * @return bool|mixed|null 处理的结果
     */
    private function processContent($content)
    {
        // 转移图片
        if (!empty($content)) {
            // 已经存在的图片
            $imgArray = [];
            // 完成处理的content
            $newContent = null;

            $ds = DIRECTORY_SEPARATOR;

            // 正则表达式匹配查找图片路径
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $count = count($matches[1]);
            for ($i=0; $i < $count; $i++) {
                $editorImg = $matches[1][$i];
                // 根据操作系统的不同对返回的saveName格式进行处理
                if ($ds == '/') {
                    $editorImg = str_replace('\\', $ds, $editorImg);
                } else {
                    $editorImg = str_replace('/', $ds, $editorImg);
                }
                // 判断是否是新上传的图片
                $position = stripos($editorImg, $ds."temp".$ds);
                if ($position > 0) {    // 新上传的图片走这里
                    // 将图片从临时temp文件夹中迁移到article文件夹中
                    // 传过来的临时文件路径为：/uploads/image/temp/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 要迁移的文件路径：/uploads/image/article/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 新建日期文件夹
                    $tempArray = explode($ds, $editorImg);
                    $imageFloder = '.'.$ds.'uploads'.$ds.'image'.$ds.'project'.$ds . $tempArray[4];
                    if (!is_dir($imageFloder)) {
                        mkdir($imageFloder, 0777, true);
                    }
                    $tempImg = '.' . $editorImg;
                    $newImg = str_replace($ds.'temp'.$ds, $ds.'project'.$ds, $tempImg);
                    // 转移图片
                    rename($tempImg, $newImg);
                } else {
                    // 已经存在的图片走这里
                    $imgArray[] = $editorImg;
                }
            }

            // 重新整理content中的图片路径
            $newContent = str_replace($ds.'temp'.$ds, $ds.'project'.$ds, $content);
            return $newContent;
        }

        return false;
    }
}
